﻿using System.Collections.Generic;
using System.Data;
using NUnit.Framework;
using SessionHunter.Business.SessionReading;
using SessionHunter.Model;
using SessionHunter.Utilities;

namespace SessionHunter.UnitTests.Business
{
    /// <summary>
    /// These unit tests will take well known session data and make sure they are correctly reverse engineered
    /// </summary>
    [TestFixture]
    public class TestSessionReading : TestBase
    {
        /// <summary>
        /// Converts a test string and then gets the session data out.
        /// </summary>
        /// <param name="sessionData">The session data.  Make sure it does not have the 0x at the start</param>
        /// <returns></returns>
        private List<SessionItem> GetSessionItems(string sessionData)
        {
            var byteData = Helper.StringToByteArray(sessionData);
            List<SessionItem> sessionItems = null;
            var sessionHelper = new SessionHelper();
            if (!sessionHelper.GetSessionItems(logger, byteData, out sessionItems))
                Assert.Fail("There was an error getting the session items out");

            return sessionItems;
        }

        #region SessionData
        /// <summary>
        /// Session data that has a dataset
        /// </summary>
        public const string DataSetSessionData = "14000000010002000000FFFFFFFF0C5465737444617461536574310C546573744461746153657432AD050000830B0000140001000000FFFFFFFF01000000000000000C020000004E53797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6237376135633536313933346530383905010000001353797374656D2E446174612E446174615365740300000017446174615365742E52656D6F74696E6756657273696F6E09586D6C536368656D610B586D6C446966664772616D0301010E53797374656D2E56657273696F6E0200000009030000000604000000B9053C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574662D3136223F3E0D0A3C78733A736368656D612069643D224E6577446174615365742220786D6C6E733D222220786D6C6E733A78733D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612220786D6C6E733A6D73646174613D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A786D6C2D6D7364617461223E0D0A20203C78733A656C656D656E74206E616D653D224E65774461746153657422206D73646174613A4973446174615365743D227472756522206D73646174613A55736543757272656E744C6F63616C653D2274727565223E0D0A202020203C78733A636F6D706C6578547970653E0D0A2020202020203C78733A63686F696365206D696E4F63637572733D223022206D61784F63637572733D22756E626F756E646564223E0D0A20202020202020203C78733A656C656D656E74206E616D653D22524252494C44554C5250494D565344504F425342223E0D0A202020202020202020203C78733A636F6D706C6578547970653E0D0A2020202020202020202020203C78733A73657175656E63653E0D0A20202020202020202020202020203C78733A656C656D656E74206E616D653D22636F6C312220747970653D2278733A737472696E6722206D73646174613A7461726765744E616D6573706163653D2222206D696E4F63637572733D223022202F3E0D0A2020202020202020202020203C2F78733A73657175656E63653E0D0A202020202020202020203C2F78733A636F6D706C6578547970653E0D0A20202020202020203C2F78733A656C656D656E743E0D0A2020202020203C2F78733A63686F6963653E0D0A202020203C2F78733A636F6D706C6578547970653E0D0A20203C2F78733A656C656D656E743E0D0A3C2F78733A736368656D613E0605000000CA033C6469666667723A646966666772616D20786D6C6E733A6D73646174613D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A786D6C2D6D73646174612220786D6C6E733A6469666667723D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A786D6C2D646966666772616D2D7631223E3C4E6577446174615365743E3C524252494C44554C5250494D565344504F425342206469666667723A69643D22524252494C44554C5250494D565344504F4253423122206D73646174613A726F774F726465723D223022206469666667723A6861734368616E6765733D22696E736572746564223E3C636F6C313E56616C7565313C2F636F6C313E3C2F524252494C44554C5250494D565344504F4253423E3C524252494C44554C5250494D565344504F425342206469666667723A69643D22524252494C44554C5250494D565344504F4253423222206D73646174613A726F774F726465723D223122206469666667723A6861734368616E6765733D22696E736572746564223E3C636F6C313E523C2F636F6C313E3C2F524252494C44554C5250494D565344504F4253423E3C2F4E6577446174615365743E3C2F6469666667723A646966666772616D3E04030000000E53797374656D2E56657273696F6E04000000065F4D616A6F72065F4D696E6F72065F4275696C64095F5265766973696F6E00000000080808080200000000000000FFFFFFFFFFFFFFFF0B140001000000FFFFFFFF01000000000000000C020000004E53797374656D2E446174612C2056657273696F6E3D342E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6237376135633536313933346530383905010000001353797374656D2E446174612E446174615365740300000017446174615365742E52656D6F74696E6756657273696F6E09586D6C536368656D610B586D6C446966664772616D0301010E53797374656D2E56657273696F6E0200000009030000000604000000BC053C3F786D6C2076657273696F6E3D22312E302220656E636F64696E673D227574662D3136223F3E0D0A3C78733A736368656D612069643D224E6577446174615365742220786D6C6E733D222220786D6C6E733A78733D22687474703A2F2F7777772E77332E6F72672F323030312F584D4C536368656D612220786D6C6E733A6D73646174613D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A786D6C2D6D7364617461223E0D0A20203C78733A656C656D656E74206E616D653D224E65774461746153657422206D73646174613A4973446174615365743D227472756522206D73646174613A55736543757272656E744C6F63616C653D2274727565223E0D0A202020203C78733A636F6D706C6578547970653E0D0A2020202020203C78733A63686F696365206D696E4F63637572733D223022206D61784F63637572733D22756E626F756E646564223E0D0A20202020202020203C78733A656C656D656E74206E616D653D22555352445448574B574B56514F484B424D4E4E57414955223E0D0A202020202020202020203C78733A636F6D706C6578547970653E0D0A2020202020202020202020203C78733A73657175656E63653E0D0A20202020202020202020202020203C78733A656C656D656E74206E616D653D22636F6C312220747970653D2278733A737472696E6722206D73646174613A7461726765744E616D6573706163653D2222206D696E4F63637572733D223022202F3E0D0A2020202020202020202020203C2F78733A73657175656E63653E0D0A202020202020202020203C2F78733A636F6D706C6578547970653E0D0A20202020202020203C2F78733A656C656D656E743E0D0A2020202020203C2F78733A63686F6963653E0D0A202020203C2F78733A636F6D706C6578547970653E0D0A20203C2F78733A656C656D656E743E0D0A3C2F78733A736368656D613E0605000000F0033C6469666667723A646966666772616D20786D6C6E733A6D73646174613D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A786D6C2D6D73646174612220786D6C6E733A6469666667723D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A786D6C2D646966666772616D2D7631223E3C4E6577446174615365743E3C555352445448574B574B56514F484B424D4E4E57414955206469666667723A69643D22555352445448574B574B56514F484B424D4E4E574149553122206D73646174613A726F774F726465723D223022206469666667723A6861734368616E6765733D22696E736572746564223E3C636F6C313E56616C7565313C2F636F6C313E3C2F555352445448574B574B56514F484B424D4E4E574149553E3C555352445448574B574B56514F484B424D4E4E57414955206469666667723A69643D22555352445448574B574B56514F484B424D4E4E574149553222206D73646174613A726F774F726465723D223122206469666667723A6861734368616E6765733D22696E736572746564223E3C636F6C313E555352445448574B574B56514F484B424D4E4E57413C2F636F6C313E3C2F555352445448574B574B56514F484B424D4E4E574149553E3C2F4E6577446174615365743E3C2F6469666667723A646966666772616D3E04030000000E53797374656D2E56657273696F6E04000000065F4D616A6F72065F4D696E6F72065F4275696C64095F5265766973696F6E00000000080808080200000000000000FFFFFFFFFFFFFFFF0BFF";
        /// <summary>
        /// Session data that has a string in it
        /// </summary>
        public const string StringSessionData = "14000000010004000000FFFFFFFF0B54657374537472696E67310B54657374537472696E67320B54657374537472696E67330B54657374537472696E673418000000240000003D0000005C00000001165447515A4D4449465256564A584D4958544759555951010A495346444A4B52474747011755514C5457515845584351455848575748454647545859011D5A4E4A464A5847524D5051474D444F4E444C48524E5A5057574B494E4AFF";
        /// <summary>
        /// Session data that has an int in it
        /// </summary>
        public const string IntSessionData = "14000000010003000000FFFFFFFF0854657374496E74310854657374496E74320854657374496E7433050000000A0000000F00000002B0DD0F4402B7C8BB640254F64C34FF";
        /// <summary>
        /// Session data that has an object we cannot resolve
        /// </summary>
        public const string ExternalObjectSessionData = "14000000010002000000FFFFFFFF0B546573744F626A656374310B546573744F626A65637432E6000000D6010000140001000000FFFFFFFF01000000000000000C0200000048546573744461746147656E657261746F722C2056657273696F6E3D312E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6E756C6C050100000021546573744461746147656E657261746F722E47656E6572617465644F626A65637402000000193C496E7456616C75653E6B5F5F4261636B696E674669656C641C3C537472696E6756616C75653E6B5F5F4261636B696E674669656C6400010802000000F5A27473060300000012585052484556435A4F444259424F415247580B140001000000FFFFFFFF01000000000000000C0200000048546573744461746147656E657261746F722C2056657273696F6E3D312E302E302E302C2043756C747572653D6E65757472616C2C205075626C69634B6579546F6B656E3D6E756C6C050100000021546573744461746147656E657261746F722E47656E6572617465644F626A65637402000000193C496E7456616C75653E6B5F5F4261636B696E674669656C641C3C537472696E6756616C75653E6B5F5F4261636B696E674669656C6400010802000000F472FD4A06030000001C50594B595A54514C4A454D51445A4B555150504753574245464D53560BFF";
        #endregion

        /// <summary>
        /// Tests some data with 3 int values stored
        /// </summary>
        [Test]
        public void GetSessionItems_TestSessionData_TestIntData()
        {
            var items = GetSessionItems(IntSessionData);
            Assert.AreEqual(items.Count, 3);
            Assert.AreEqual(items[0].Key, "TestInt1");
            Assert.AreEqual(items[0].DisplayKey, "TestInt1 (Int32)");
            Assert.AreEqual(items[0].Item.ToString(), "1141890480");
            Assert.AreEqual(items[0].Size, 4);
            Assert.AreEqual(items[1].Key, "TestInt2");
            Assert.AreEqual(items[1].DisplayKey, "TestInt2 (Int32)");
            Assert.AreEqual(items[1].Item.ToString(), "1690028215");
            Assert.AreEqual(items[1].Size, 4);
            Assert.AreEqual(items[2].Key, "TestInt3");
            Assert.AreEqual(items[2].DisplayKey, "TestInt3 (Int32)");
            Assert.AreEqual(items[2].Item.ToString(), "877459028");
            Assert.AreEqual(items[2].Size, 4);
        }

        /// <summary>
        /// Tests some data with 4 string values stored
        /// </summary>
        [Test]
        public void GetSessionItems_TestSessionData_TestStringData()
        {
            var items = GetSessionItems(StringSessionData);
            Assert.AreEqual(items.Count, 4);
            Assert.AreEqual(items[0].Key, "TestString1");
            Assert.AreEqual(items[0].DisplayKey, "TestString1 (String)");
            Assert.AreEqual(items[0].Item.ToString(), "TGQZMDIFRVVJXMIXTGYUYQ");
            Assert.AreEqual(items[0].Size, 23);
            Assert.AreEqual(items[1].Key, "TestString2");
            Assert.AreEqual(items[1].DisplayKey, "TestString2 (String)");
            Assert.AreEqual(items[1].Item.ToString(), "ISFDJKRGGG");
            Assert.AreEqual(items[1].Size, 11);
            Assert.AreEqual(items[2].Key, "TestString3");
            Assert.AreEqual(items[2].DisplayKey, "TestString3 (String)");
            Assert.AreEqual(items[2].Item.ToString(), "UQLTWQXEXCQEXHWWHEFGTXY");
            Assert.AreEqual(items[2].Size, 24);
            Assert.AreEqual(items[3].Key, "TestString4");
            Assert.AreEqual(items[3].DisplayKey, "TestString4 (String)");
            Assert.AreEqual(items[3].Item.ToString(), "ZNJFJXGRMPQGMDONDLHRNZPWWKINJ");
            Assert.AreEqual(items[3].Size, 30);
        }

        /// <summary>
        /// Tests some data with 2 datasets
        /// </summary>
        [Test]
        public void GetSessionItems_TestSessionData_TestDataSets()
        {
            var items = GetSessionItems(DataSetSessionData);
            Assert.AreEqual(items.Count, 2);
            Assert.AreEqual("TestDataSet1", items[0].Key);
            Assert.AreEqual("System.Data.DataSet", items[0].Item.ToString());
            Assert.AreEqual("TestDataSet1 (DataSet)", items[0].DisplayKey);
            Assert.AreEqual(1452, items[0].Size);
            Assert.AreEqual("TestDataSet2", items[1].Key);
            Assert.AreEqual("System.Data.DataSet", items[1].Item.ToString());
            Assert.AreEqual("TestDataSet2 (DataSet)", items[1].DisplayKey);
            Assert.AreEqual(1493, items[1].Size);

            // Make sure we have a valid table
            var dt = ((DataSet)items[0].Item).Tables[0];
            Assert.AreEqual(dt.TableName, "RBRILDULRPIMVSDPOBSB");
        }

        /// <summary>
        /// Tests to see how deserialization works when we reference an external object
        /// </summary>
        [Test]
        public void GetSessionItems_TestSessionData_TestExternalObject()
        {
            var items = GetSessionItems(ExternalObjectSessionData);
            Assert.AreEqual(items.Count, 2);
            Assert.AreEqual("TestObject1", items[0].Key);
            Assert.AreEqual("TestDataGenerator.GeneratedObject", items[0].Item.ToString());
            Assert.AreEqual("TestObject1 (GeneratedObject)", items[0].DisplayKey);
            Assert.AreEqual(229, items[0].Size);
            Assert.AreEqual("TestObject2", items[1].Key);
            Assert.AreEqual("TestDataGenerator.GeneratedObject", items[1].Item.ToString());
            Assert.AreEqual("TestObject2 (GeneratedObject)", items[1].DisplayKey);
            Assert.AreEqual(239, items[1].Size);
        }

    }
}
